import { ComponentDefinitionHelper } from './componentDefinition';
import { uuid } from '@CIF/Utils/util';
import _ from 'lodash';
import { reduceConfig, collectCallbackConfigPath } from '@CIF/Utils/reduce-config';
import { usePrimaryStore } from '@/store';

/**
 * 从组件开发时定义的data.config.js和main.config.js解析得出
 * 用于定义和维护组件使用时组件实例信息
 * 包含各种可配置项的输出
 *
 * 这里的配置项并未经过 reduceConfig 工具函数转换过，所以是数组而不是对象
 */
class ComponentInstance {
	/**
	 * 组件实例id, uuid()函数生成
	 *
	 * @memberof ComponentInstance
	 */
	uuid = '';
	/**
	 * 组件定义引用，在组件实例化时将定义与此成员变量绑定
	 *
	 * @memberof ComponentInstance
	 */
	definitionId = '';
	/**
	 * 组件定义的引用
	 *
	 * @memberof ComponentInstance
	 */
	definitionRefrence = undefined;
	/**
	 * 组件树节点名
	 *
	 * @memberof ComponentInstance
	 */
	name = '组件树节点名';
	/**
	 * 组件icon
	 *
	 * @memberof ComponentInstance
	 */
	icon = '';
	/**
	 * 组件主题
	 *
	 * @memberof ComponentInstance
	 */
	theme = {};
	/**
	 * 组件宽度，number类型
	 *
	 * @memberof ComponentInstance
	 */
	width = 0;
	/**
	 * 组件高度，number类型
	 *
	 * @memberof ComponentInstance
	 */
	height = 0;
	/**
	 * 距离画布的左边距，number类型
	 *
	 * @memberof ComponentInstance
	 */
	left = 0;
	/**
	 * 距离画布的顶边距，number类型
	 *
	 * @memberof ComponentInstance
	 */
	top = 0;
	/**
	 * 距离画布的右边距，number类型
	 *
	 * @memberof ComponentInstance
	 */
	right = 0;
	/**
	 * 距离画布的底边距，number类型
	 *
	 * @memberof ComponentInstance
	 */
	bottom = 0;
	/**
	 * 组件定位类型，确定组件到底基于左上、右上、左下还是右下
	 * 枚举：0（左上）、1（右上）、2（左下）、3（右下）
	 *
	 * @memberof ComponentInstance
	 */
	positionType = 0;
	/**
	 * 最终给组件引用的数据
	 *
	 * @memberof ComponentInstance
	 */
	data = [];
	/**
	 * data字段校验
	 *
	 * @memberof ComponentInstance
	 */
	fields = [];
	/**
	 * 数据源类型，枚举：interalData = -1、staticData = 0、apiData = 1、 serviceListData = 2
	 *
	 * @memberof ComponentInstance
	 */
	dataSourceType = 0;
	/**
	 * 数据源刷新时间
	 */
	dataRefreshTime = 0;
	// /**
	//  * 容器组件子组件 uuid 数组
	//  *
	//  * @memberof ComponentInstance
	//  */
	// children = []
	/**
	 * 组件可配置项的输出
	 * 值为经过 reduce-config 工具类处理后得出的 [key:value] 形式的对象
	 * 将会被作为本实例对应的 Vue 组件的 Props
	 *
	 * @memberof ComponentInstance
	 */
	configData = {};
	/**
   * 用户通过event和action形成的自定义交互事件
   * 值为二维对象数组，数据格式
   * {
        event: "", //事件
        cpntIds: "",//cpnt的uuid
        cpntNames:"",//cpnt的name
        action:"",//cpnt的动作
        actionConfig:{},//cpnt的动作配置
      }
   *
   * @memberof ComponentInstance
   */
	interactions = [];
	/**
	 * 用户设置回调字段，包括字段值和变量名
	 * 字段值 origin ：组件数据中对应的字段值，也是回调池value的来源
	 * 变量名 target ：放入全局回调池的变量名
	 *
	 * @memberof ComponentInstance
	 */
	callbackArgs = [];
	/**
	 * 用户设置过滤器，衔接回调池中的回调字段
	 *
	 * @memberof ComponentInstance
	 */
	filterCbVar = [];
	/**
	 * api数据源参数列表中的回调字段
	 *
	 * @memberof ComponentInstance
	 */
	fetcherCbVar = [];
	/**
   * 用户存储过滤器函数体，用于过滤器实现
   * {
        fn: string,//过滤器函数体
        active: boolean,//当前选定状态
      }
   *
   * @memberof ComponentInstance
   */
	dataFormatter = {
		filterFn: 'return data',
		active: false
	};
	/**
	 * 包含自己的数据过滤器
	 *
	 * @memberof ComponentInstance
	 */
	apiFormatter = '';

	styleFormatter = '';

	eventFormatter = '';

	callbackConfigData = {};

	#callbackConfigPath = [];

	/**
	 * 这个构造器用于parse整个组件树，非用于手动添加组件实例
	 * 手动添加组件实例用 ComponentInstanceHelper.getNewInstance 函数
	 * @param {*} instance
	 */
	constructor(instance = {}) {
		const defId = _.get(instance, 'definitionId', undefined);
		if (_.isNil(defId) || typeof defId !== 'string') {
			throw new Error(`组件${this.uuid}未引用定义!`);
		}
		this.definitionId = instance.definitionId;

		this.uuid = instance.uuid || uuid();

		if (_.isNil(this.definitionRefrence)) {
			this.definitionRefrence = ComponentDefinitionHelper.getDef(instance.definitionId);
			if (_.isNil(this.definitionRefrence)) {
				throw new Error(
					`组件${instance.name}:${instance.definitionId}定义缺失，请检查：1. 组件文件是否存在；2. 组件moduleName因重复被其它组件占用`
				);
			}
		}

		this.name = !_.isNil(instance.name)
			? instance.name
			: _.get(this.definitionRefrence, 'name', '');
		this.icon = !_.isNil(instance.icon)
			? instance.icon
			: _.get(this.definitionRefrence, 'icon', '');
		this.theme = !_.isNil(instance.theme)
			? instance.theme
			: _.get(this.definitionRefrence, 'theme', {});
		this.width = !_.isNil(instance.width)
			? instance.width
			: _.get(this.definitionRefrence, 'width', 0);
		this.height = !_.isNil(instance.height)
			? instance.height
			: _.get(this.definitionRefrence, 'height', 0);
		this.left = !_.isNil(instance.left) ? instance.left : _.get(this.definitionRefrence, 'left', 0);
		this.top = !_.isNil(instance.top) ? instance.top : _.get(this.definitionRefrence, 'top', 0);
		this.right = !_.isNil(instance.right)
			? instance.right
			: _.get(this.definitionRefrence, 'right', 0);
		this.bottom = !_.isNil(instance.bottom)
			? instance.bottom
			: _.get(this.definitionRefrence, 'bottom', 0);
		this.positionType = !_.isNil(instance.positionType)
			? instance.positionType
			: _.get(this.definitionRefrence, 'positionType', 0);
		this.data = !_.isNil(instance.data)
			? instance.data
			: _.cloneDeep(_.get(this.definitionRefrence, 'data', []));
		this.fields = !_.isNil(instance.fields)
			? _.cloneDeep(_.get(this.definitionRefrence, 'fields', [])).map((x) => {
					return { ...x, status: false };
				})
			: [];
		this.dataSourceType = _.get(instance, 'dataSourceType', 0);
		this.dataRefreshTime = _.get(instance, 'dataRefreshTime', 0);
		// this.children = _.get(instance, "children", [])

		this.configData = !_.isNil(instance.configData)
			? instance.configData
			: reduceConfig(_.get(this.definitionRefrence, 'configuration', []));
		this.interactions = _.get(instance, 'interactions', []);
		// this.callbackArgs = _.get(instance, "callbackArgs", [{origin: "aa", target:"K1"},{origin: "bb", target:"K2"}])
		this.callbackArgs = _.get(instance, 'callbackArgs', []);
		// this.filterCbVar = _.get(instance, "filterCbVar", ["K1", "K2"])
		this.filterCbVar = _.get(instance, 'filterCbVar', []);

		this.dataFormatter = _.get(instance, 'dataFormatter', {
			filterFn: 'return data',
			active: false
		});
		this.apiFormatter = _.get(instance, 'apiFormatter', '');
		this.styleFormatter = _.get(instance, 'styleFormatter', '');
		this.eventFormatter = _.get(instance, 'eventFormatter', '');

		this.#callbackConfigPath = collectCallbackConfigPath(
			_.get(this, 'definitionRefrence.configuration')
		);
		const callbackConfigData = {};
		this.#callbackConfigPath.forEach((path) => {
			callbackConfigData[path] = undefined;
		});
		this.callbackConfigData = callbackConfigData;

		// 序列化store结构
		this.#serializationStoreCallbackpool();
	}

	get getCallbackConfigData() {
		// console.log('call getter callbackConfigData');
		return _.cloneDeep(this.callbackConfigData);
	}

	get callbackConfigPath() {
		// console.log('call getter callbackConfigPath');
		return _.cloneDeep(this.#callbackConfigPath);
	}

	getDataSource = (data) => {
		return eval(this.dataFormatter.filterFn)(data);
	};

	getStyle = (data) => {
		return eval(this.styleFormatter)(data);
	};

	getEvent = (data) => {
		return data;
	};

	getAction = (data) => {
		return data;
	};

	/**
	 * 将实例的interactionCallbackArgs序列化入store的结构中
	 */
	#serializationStoreCallbackpool() {
		const store = usePrimaryStore();
		store.serializationCallbackPool(this);
	}

	// // TODO consider add setter and getter for left , right, top and bottom properties
	// /**
	//  * @param {number} num
	//  */
	// set left(num) {
	//   if (typeof num !== 'number') {
	//     return
	//   }
	//   this.left = num
	// }
}

export default ComponentInstance;

// /**
//  * CIF内部全局存储组件定义用
//  */
// export const ComponentInstanceHelper = {
//   getNewInstance: (cpntDefineId) => {
//     const cpntDefine = ComponentDefinitionHelper.getDef(cpntDefineId)
//     const instance = new ComponentInstance({
//       definitionId: cpntDefine.id,
//       definitionRefrence: cpntDefine
//     })
//     // instance.data = Object.assign([], cpntDefine.data) // 深拷贝
//     return instance
//   },
// }
